{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# 子图布局和间距 (Subplot Layout and Spacing) 教程\n",
        "\n",
        "本部分将详细讲解如何调整子图的布局和间距，以及如何设置子图标题和标签。\n",
        "\n",
        "## 学习内容\n",
        "1. **调整子图间距**\n",
        "   - `plt.tight_layout()`：自动调整布局\n",
        "   - `plt.subplots_adjust()`：手动调整间距\n",
        "   - 参数：`left`, `right`, `top`, `bottom`, `wspace`, `hspace`\n",
        "\n",
        "2. **子图标题和标签**\n",
        "   - `ax.set_title()`：设置子图标题\n",
        "   - `fig.suptitle()`：设置总标题\n",
        "   - `fig.supxlabel()` 和 `fig.supylabel()`：设置总坐标轴标签\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 导入必要的库\n",
        "import matplotlib.pyplot as plt\n",
        "import numpy as np\n",
        "\n",
        "# 设置中文字体（如果需要显示中文）\n",
        "plt.rcParams['font.sans-serif'] = ['PingFang SC', 'Arial Unicode MS']\n",
        "plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题\n",
        "\n",
        "# 在 Jupyter Notebook 中内联显示图形\n",
        "%matplotlib inline\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 第一部分：调整子图间距\n",
        "\n",
        "当创建多个子图时，它们可能会重叠或间距不合适。Matplotlib 提供了两种方法来调整子图的间距：自动调整和手动调整。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 1.1 plt.tight_layout()：自动调整布局\n",
        "\n",
        "`plt.tight_layout()` 是最简单的方法，它会自动调整子图参数，使子图标签和标题不会重叠。\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "plt.tight_layout(pad=1.08, h_pad=None, w_pad=None, rect=None)\n",
        "```\n",
        "\n",
        "**参数说明**：\n",
        "- `pad`：子图之间的填充（以字体大小为单位），默认 1.08\n",
        "- `h_pad`：垂直方向的填充（可选）\n",
        "- `w_pad`：水平方向的填充（可选）\n",
        "- `rect`：调整后的子图区域（可选，格式：`[left, bottom, right, top]`）\n",
        "\n",
        "**返回值**：\n",
        "- 无返回值，直接修改当前图形\n",
        "\n",
        "**使用场景**：\n",
        "- 大多数情况下，使用默认参数即可\n",
        "- 当子图标题或标签重叠时\n",
        "- 快速调整布局，无需手动计算\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 1：不使用 tight_layout() 的问题\n",
        "x = np.linspace(0, 10, 100)\n",
        "\n",
        "# 不使用 tight_layout() - 标题和标签可能重叠\n",
        "fig, axes = plt.subplots(2, 2, figsize=(10, 8))\n",
        "axes[0, 0].plot(x, np.sin(x), 'b-', linewidth=2)\n",
        "axes[0, 0].set_title('子图标题可能很长，会重叠', fontsize=14)\n",
        "axes[0, 0].set_xlabel('x 轴标签', fontsize=12)\n",
        "axes[0, 0].set_ylabel('y 轴标签', fontsize=12)\n",
        "axes[0, 0].grid(True, alpha=0.3)\n",
        "\n",
        "axes[0, 1].plot(x, np.cos(x), 'r-', linewidth=2)\n",
        "axes[0, 1].set_title('另一个很长的子图标题', fontsize=14)\n",
        "axes[0, 1].set_xlabel('x 轴标签', fontsize=12)\n",
        "axes[0, 1].set_ylabel('y 轴标签', fontsize=12)\n",
        "axes[0, 1].grid(True, alpha=0.3)\n",
        "\n",
        "axes[1, 0].plot(x, np.tan(x), 'g-', linewidth=2)\n",
        "axes[1, 0].set_title('第三个子图标题', fontsize=14)\n",
        "axes[1, 0].set_xlabel('x 轴标签', fontsize=12)\n",
        "axes[1, 0].set_ylabel('y 轴标签', fontsize=12)\n",
        "axes[1, 0].set_ylim(-5, 5)\n",
        "axes[1, 0].grid(True, alpha=0.3)\n",
        "\n",
        "axes[1, 1].plot(x, np.sin(x) * np.cos(x), 'm-', linewidth=2)\n",
        "axes[1, 1].set_title('第四个子图标题', fontsize=14)\n",
        "axes[1, 1].set_xlabel('x 轴标签', fontsize=12)\n",
        "axes[1, 1].set_ylabel('y 轴标签', fontsize=12)\n",
        "axes[1, 1].grid(True, alpha=0.3)\n",
        "\n",
        "plt.suptitle('不使用 tight_layout() - 标题和标签可能重叠', fontsize=16, fontweight='bold')\n",
        "plt.show()\n",
        "\n",
        "# 使用 tight_layout() - 自动调整\n",
        "fig, axes = plt.subplots(2, 2, figsize=(10, 8))\n",
        "axes[0, 0].plot(x, np.sin(x), 'b-', linewidth=2)\n",
        "axes[0, 0].set_title('子图标题可能很长，会重叠', fontsize=14)\n",
        "axes[0, 0].set_xlabel('x 轴标签', fontsize=12)\n",
        "axes[0, 0].set_ylabel('y 轴标签', fontsize=12)\n",
        "axes[0, 0].grid(True, alpha=0.3)\n",
        "\n",
        "axes[0, 1].plot(x, np.cos(x), 'r-', linewidth=2)\n",
        "axes[0, 1].set_title('另一个很长的子图标题', fontsize=14)\n",
        "axes[0, 1].set_xlabel('x 轴标签', fontsize=12)\n",
        "axes[0, 1].set_ylabel('y 轴标签', fontsize=12)\n",
        "axes[0, 1].grid(True, alpha=0.3)\n",
        "\n",
        "axes[1, 0].plot(x, np.tan(x), 'g-', linewidth=2)\n",
        "axes[1, 0].set_title('第三个子图标题', fontsize=14)\n",
        "axes[1, 0].set_xlabel('x 轴标签', fontsize=12)\n",
        "axes[1, 0].set_ylabel('y 轴标签', fontsize=12)\n",
        "axes[1, 0].set_ylim(-5, 5)\n",
        "axes[1, 0].grid(True, alpha=0.3)\n",
        "\n",
        "axes[1, 1].plot(x, np.sin(x) * np.cos(x), 'm-', linewidth=2)\n",
        "axes[1, 1].set_title('第四个子图标题', fontsize=14)\n",
        "axes[1, 1].set_xlabel('x 轴标签', fontsize=12)\n",
        "axes[1, 1].set_ylabel('y 轴标签', fontsize=12)\n",
        "axes[1, 1].grid(True, alpha=0.3)\n",
        "\n",
        "plt.suptitle('使用 tight_layout() - 自动调整布局', fontsize=16, fontweight='bold')\n",
        "plt.tight_layout()  # 自动调整布局\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": []
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 2：不同 pad 参数的效果\n",
        "x = np.linspace(0, 10, 100)\n",
        "\n",
        "# pad=0.5（较小间距）\n",
        "fig, axes = plt.subplots(2, 2, figsize=(10, 8))\n",
        "for i, ax in enumerate(axes.flatten()):\n",
        "    ax.plot(x, np.sin(x + i*0.5), 'b-', linewidth=2)\n",
        "    ax.set_title(f'子图 {i+1}', fontsize=12)\n",
        "    ax.set_xlabel('x 轴', fontsize=10)\n",
        "    ax.set_ylabel('y 轴', fontsize=10)\n",
        "    ax.grid(True, alpha=0.3)\n",
        "plt.suptitle('pad=0.5（较小间距）', fontsize=14, fontweight='bold')\n",
        "plt.tight_layout(pad=0.5)\n",
        "plt.show()\n",
        "\n",
        "# pad=2.0（较大间距）\n",
        "fig, axes = plt.subplots(2, 2, figsize=(10, 8))\n",
        "for i, ax in enumerate(axes.flatten()):\n",
        "    ax.plot(x, np.sin(x + i*0.5), 'b-', linewidth=2)\n",
        "    ax.set_title(f'子图 {i+1}', fontsize=12)\n",
        "    ax.set_xlabel('x 轴', fontsize=10)\n",
        "    ax.set_ylabel('y 轴', fontsize=10)\n",
        "    ax.grid(True, alpha=0.3)\n",
        "plt.suptitle('pad=2.0（较大间距）', fontsize=14, fontweight='bold')\n",
        "plt.tight_layout(pad=2.0)\n",
        "plt.show()\n",
        "\n",
        "# 分别设置 h_pad 和 w_pad\n",
        "fig, axes = plt.subplots(2, 2, figsize=(10, 8))\n",
        "for i, ax in enumerate(axes.flatten()):\n",
        "    ax.plot(x, np.sin(x + i*0.5), 'b-', linewidth=2)\n",
        "    ax.set_title(f'子图 {i+1}', fontsize=12)\n",
        "    ax.set_xlabel('x 轴', fontsize=10)\n",
        "    ax.set_ylabel('y 轴', fontsize=10)\n",
        "    ax.grid(True, alpha=0.3)\n",
        "plt.suptitle('h_pad=3.0, w_pad=1.0（垂直间距大，水平间距小）', fontsize=14, fontweight='bold')\n",
        "plt.tight_layout(h_pad=3.0, w_pad=1.0)\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 1.3 plt.subplots_adjust()：手动调整间距\n",
        "\n",
        "`plt.subplots_adjust()` 提供了更精确的控制，可以手动设置子图的边距和间距。\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "plt.subplots_adjust(left=None, bottom=None, right=None, top=None, \n",
        "                    wspace=None, hspace=None)\n",
        "```\n",
        "\n",
        "**参数说明**：\n",
        "- `left`：左边距（0-1 之间，相对于图形宽度）\n",
        "- `right`：右边距（0-1 之间，相对于图形宽度）\n",
        "- `bottom`：底边距（0-1 之间，相对于图形高度）\n",
        "- `top`：顶边距（0-1 之间，相对于图形高度）\n",
        "- `wspace`：水平方向子图之间的间距（相对于子图平均宽度）\n",
        "- `hspace`：垂直方向子图之间的间距（相对于子图平均高度）\n",
        "\n",
        "**注意事项**：\n",
        "- 所有参数都是相对于图形大小的比例（0-1 之间）\n",
        "- `left` < `right`，`bottom` < `top`\n",
        "- `wspace` 和 `hspace` 可以是任意正数，表示子图宽/高的倍数\n",
        "\n",
        "**使用场景**：\n",
        "- 需要精确控制布局时\n",
        "- `tight_layout()` 无法满足需求时\n",
        "- 需要为总标题预留空间时\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 3：使用 subplots_adjust() 手动调整\n",
        "x = np.linspace(0, 10, 100)\n",
        "\n",
        "# 默认布局\n",
        "fig, axes = plt.subplots(2, 2, figsize=(10, 8))\n",
        "for i, ax in enumerate(axes.flatten()):\n",
        "    ax.plot(x, np.sin(x + i*0.5), 'b-', linewidth=2)\n",
        "    ax.set_title(f'子图 {i+1}', fontsize=12)\n",
        "    ax.set_xlabel('x 轴', fontsize=10)\n",
        "    ax.set_ylabel('y 轴', fontsize=10)\n",
        "    ax.grid(True, alpha=0.3)\n",
        "plt.suptitle('默认布局', fontsize=14, fontweight='bold')\n",
        "plt.show()\n",
        "\n",
        "# 增加边距（为总标题预留空间）\n",
        "fig, axes = plt.subplots(2, 2, figsize=(10, 8))\n",
        "for i, ax in enumerate(axes.flatten()):\n",
        "    ax.plot(x, np.sin(x + i*0.5), 'b-', linewidth=2)\n",
        "    ax.set_title(f'子图 {i+1}', fontsize=12)\n",
        "    ax.set_xlabel('x 轴', fontsize=10)\n",
        "    ax.set_ylabel('y 轴', fontsize=10)\n",
        "    ax.grid(True, alpha=0.3)\n",
        "plt.suptitle('增加边距（为总标题预留空间）', fontsize=16, fontweight='bold')\n",
        "plt.subplots_adjust(left=0.1, bottom=0.1, right=0.95, top=0.9, wspace=0.3, hspace=0.3)\n",
        "plt.show()\n",
        "\n",
        "# 增加子图间距\n",
        "fig, axes = plt.subplots(2, 2, figsize=(10, 8))\n",
        "for i, ax in enumerate(axes.flatten()):\n",
        "    ax.plot(x, np.sin(x + i*0.5), 'b-', linewidth=2)\n",
        "    ax.set_title(f'子图 {i+1}', fontsize=12)\n",
        "    ax.set_xlabel('x 轴', fontsize=10)\n",
        "    ax.set_ylabel('y 轴', fontsize=10)\n",
        "    ax.grid(True, alpha=0.3)\n",
        "plt.suptitle('增加子图间距（wspace=0.5, hspace=0.5）', fontsize=14, fontweight='bold')\n",
        "plt.subplots_adjust(wspace=0.5, hspace=0.5)\n",
        "plt.show()\n",
        "\n",
        "# 减少子图间距（紧凑布局）\n",
        "fig, axes = plt.subplots(2, 2, figsize=(10, 8))\n",
        "for i, ax in enumerate(axes.flatten()):\n",
        "    ax.plot(x, np.sin(x + i*0.5), 'b-', linewidth=2)\n",
        "    ax.set_title(f'子图 {i+1}', fontsize=12)\n",
        "    ax.set_xlabel('x 轴', fontsize=10)\n",
        "    ax.set_ylabel('y 轴', fontsize=10)\n",
        "    ax.grid(True, alpha=0.3)\n",
        "plt.suptitle('减少子图间距（紧凑布局）', fontsize=14, fontweight='bold')\n",
        "plt.subplots_adjust(wspace=0.1, hspace=0.1)\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 1.4 边距参数详解\n",
        "\n",
        "理解边距参数的含义对于精确控制布局非常重要。\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 4：边距参数详解\n",
        "x = np.linspace(0, 10, 100)\n",
        "\n",
        "# 可视化边距参数的含义\n",
        "fig, axes = plt.subplots(2, 2, figsize=(12, 10))\n",
        "\n",
        "# 默认边距\n",
        "axes[0, 0].plot(x, np.sin(x), 'b-', linewidth=2)\n",
        "axes[0, 0].set_title('默认边距\\n(left=0.125, right=0.9, bottom=0.1, top=0.9)', fontsize=10)\n",
        "axes[0, 0].grid(True, alpha=0.3)\n",
        "axes[0, 0].text(5, 0, '默认边距', fontsize=12, ha='center', \n",
        "                bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))\n",
        "\n",
        "# 增加左边距\n",
        "axes[0, 1].plot(x, np.cos(x), 'r-', linewidth=2)\n",
        "axes[0, 1].set_title('增加左边距\\n(left=0.2)', fontsize=10)\n",
        "axes[0, 1].grid(True, alpha=0.3)\n",
        "axes[0, 1].text(5, 0, '左边距更大', fontsize=12, ha='center',\n",
        "                bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))\n",
        "\n",
        "# 增加底边距\n",
        "axes[1, 0].plot(x, np.tan(x), 'g-', linewidth=2)\n",
        "axes[1, 0].set_title('增加底边距\\n(bottom=0.2)', fontsize=10)\n",
        "axes[1, 0].set_ylim(-5, 5)\n",
        "axes[1, 0].grid(True, alpha=0.3)\n",
        "axes[1, 0].text(5, 0, '底边距更大', fontsize=12, ha='center',\n",
        "                bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))\n",
        "\n",
        "# 同时调整多个边距\n",
        "axes[1, 1].plot(x, np.sin(x) * np.cos(x), 'm-', linewidth=2)\n",
        "axes[1, 1].set_title('同时调整多个边距\\n(left=0.15, bottom=0.15, right=0.85, top=0.85)', fontsize=10)\n",
        "axes[1, 1].grid(True, alpha=0.3)\n",
        "axes[1, 1].text(5, 0, '所有边距都增加', fontsize=12, ha='center',\n",
        "                bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))\n",
        "\n",
        "plt.suptitle('边距参数效果对比', fontsize=16, fontweight='bold')\n",
        "plt.subplots_adjust(left=0.2, bottom=0.2, right=0.85, top=0.85, wspace=0.3, hspace=0.3)\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 第二部分：子图标题和标签\n",
        "\n",
        "为子图添加标题和标签可以让图表更加清晰和易于理解。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.1 ax.set_title()：设置子图标题\n",
        "\n",
        "每个子图都可以有自己的标题，使用 `ax.set_title()` 方法设置。\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "ax.set_title(label, fontsize=None, fontweight=None, loc=None, pad=None)\n",
        "```\n",
        "\n",
        "**参数说明**：\n",
        "- `label`：标题文本\n",
        "- `fontsize`：字体大小\n",
        "- `fontweight`：字体粗细（`'normal'`, `'bold'` 等）\n",
        "- `loc`：标题位置（`'left'`, `'center'`, `'right'`，默认 `'center'`）\n",
        "- `pad`：标题与子图的间距\n",
        "\n",
        "**使用场景**：\n",
        "- 为每个子图添加描述性标题\n",
        "- 区分不同的数据系列或图表类型\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 5：设置子图标题\n",
        "x = np.linspace(0, 10, 100)\n",
        "\n",
        "fig, axes = plt.subplots(2, 2, figsize=(12, 8))\n",
        "\n",
        "# 默认标题（居中）\n",
        "axes[0, 0].plot(x, np.sin(x), 'b-', linewidth=2)\n",
        "axes[0, 0].set_title('默认标题（居中）', fontsize=12)\n",
        "axes[0, 0].grid(True, alpha=0.3)\n",
        "\n",
        "# 左对齐标题\n",
        "axes[0, 1].plot(x, np.cos(x), 'r-', linewidth=2)\n",
        "axes[0, 1].set_title('左对齐标题', fontsize=12, loc='left')\n",
        "axes[0, 1].grid(True, alpha=0.3)\n",
        "\n",
        "# 右对齐标题\n",
        "axes[1, 0].plot(x, np.tan(x), 'g-', linewidth=2)\n",
        "axes[1, 0].set_title('右对齐标题', fontsize=12, loc='right')\n",
        "axes[1, 0].set_ylim(-5, 5)\n",
        "axes[1, 0].grid(True, alpha=0.3)\n",
        "\n",
        "# 粗体标题\n",
        "axes[1, 1].plot(x, np.sin(x) * np.cos(x), 'm-', linewidth=2)\n",
        "axes[1, 1].set_title('粗体标题', fontsize=14, fontweight='bold')\n",
        "axes[1, 1].grid(True, alpha=0.3)\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()\n",
        "\n",
        "# 不同字体大小的标题\n",
        "fig, axes = plt.subplots(1, 3, figsize=(15, 4))\n",
        "for i, (ax, size) in enumerate(zip(axes, [10, 14, 18])):\n",
        "    ax.plot(x, np.sin(x + i), 'b-', linewidth=2)\n",
        "    ax.set_title(f'字体大小 {size}', fontsize=size)\n",
        "    ax.grid(True, alpha=0.3)\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.2 fig.suptitle()：设置总标题\n",
        "\n",
        "`fig.suptitle()` 用于为整个图形设置总标题，显示在所有子图的上方。\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "fig.suptitle(t, x=0.5, y=0.98, ha='center', va='top', fontsize=None, fontweight=None)\n",
        "```\n",
        "\n",
        "**参数说明**：\n",
        "- `t`：标题文本\n",
        "- `x`：标题的 x 位置（0-1 之间，相对于图形宽度）\n",
        "- `y`：标题的 y 位置（0-1 之间，相对于图形高度）\n",
        "- `ha`：水平对齐（`'left'`, `'center'`, `'right'`）\n",
        "- `va`：垂直对齐（`'top'`, `'center'`, `'bottom'`）\n",
        "- `fontsize`：字体大小\n",
        "- `fontweight`：字体粗细\n",
        "\n",
        "**使用场景**：\n",
        "- 为整个图形添加总体描述\n",
        "- 说明所有子图的共同主题\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 6：设置总标题\n",
        "x = np.linspace(0, 10, 100)\n",
        "\n",
        "# 默认总标题（居中，顶部）\n",
        "fig, axes = plt.subplots(2, 2, figsize=(12, 8))\n",
        "for i, ax in enumerate(axes.flatten()):\n",
        "    ax.plot(x, np.sin(x + i*0.5), 'b-', linewidth=2)\n",
        "    ax.set_title(f'子图 {i+1}', fontsize=12)\n",
        "    ax.grid(True, alpha=0.3)\n",
        "fig.suptitle('默认总标题（居中，顶部）', fontsize=16, fontweight='bold')\n",
        "plt.tight_layout()\n",
        "plt.show()\n",
        "\n",
        "# 调整总标题位置\n",
        "fig, axes = plt.subplots(2, 2, figsize=(12, 8))\n",
        "for i, ax in enumerate(axes.flatten()):\n",
        "    ax.plot(x, np.sin(x + i*0.5), 'b-', linewidth=2)\n",
        "    ax.set_title(f'子图 {i+1}', fontsize=12)\n",
        "    ax.grid(True, alpha=0.3)\n",
        "fig.suptitle('调整位置的总标题 (x=0.3, y=0.995)', fontsize=16, fontweight='bold', \n",
        "             x=0.3, y=0.995, ha='left')\n",
        "plt.tight_layout()\n",
        "plt.show()\n",
        "\n",
        "# 不同字体大小的总标题\n",
        "fig, axes = plt.subplots(2, 2, figsize=(12, 8))\n",
        "for i, ax in enumerate(axes.flatten()):\n",
        "    ax.plot(x, np.sin(x + i*0.5), 'b-', linewidth=2)\n",
        "    ax.set_title(f'子图 {i+1}', fontsize=12)\n",
        "    ax.grid(True, alpha=0.3)\n",
        "fig.suptitle('大号总标题 (fontsize=20)', fontsize=20, fontweight='bold')\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.3 fig.supxlabel() 和 fig.supylabel()：设置总坐标轴标签\n",
        "\n",
        "`fig.supxlabel()` 和 `fig.supylabel()` 用于为整个图形设置统一的 x 轴和 y 轴标签，这在共享坐标轴时特别有用。\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "fig.supxlabel(t, x=0.5, y=0.02, ha='center', va='bottom', fontsize=None)\n",
        "fig.supylabel(t, x=0.02, y=0.5, ha='left', va='center', fontsize=None)\n",
        "```\n",
        "\n",
        "**参数说明**：\n",
        "- `t`：标签文本\n",
        "- `x`, `y`：标签位置（0-1 之间）\n",
        "- `ha`：水平对齐\n",
        "- `va`：垂直对齐\n",
        "- `fontsize`：字体大小\n",
        "\n",
        "**使用场景**：\n",
        "- 当所有子图共享相同的坐标轴时\n",
        "- 避免在每个子图上重复设置标签\n",
        "- 创建更整洁的图表布局\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 7：设置总坐标轴标签\n",
        "x = np.linspace(0, 10, 100)\n",
        "\n",
        "# 使用总坐标轴标签（共享 x 轴）\n",
        "fig, axes = plt.subplots(2, 2, figsize=(12, 8), sharex=True)\n",
        "axes[0, 0].plot(x, np.sin(x), 'b-', linewidth=2)\n",
        "axes[0, 0].set_title('子图 1', fontsize=12)\n",
        "axes[0, 0].grid(True, alpha=0.3)\n",
        "\n",
        "axes[0, 1].plot(x, np.cos(x), 'r-', linewidth=2)\n",
        "axes[0, 1].set_title('子图 2', fontsize=12)\n",
        "axes[0, 1].grid(True, alpha=0.3)\n",
        "\n",
        "axes[1, 0].plot(x, np.tan(x), 'g-', linewidth=2)\n",
        "axes[1, 0].set_title('子图 3', fontsize=12)\n",
        "axes[1, 0].set_ylim(-5, 5)\n",
        "axes[1, 0].grid(True, alpha=0.3)\n",
        "\n",
        "axes[1, 1].plot(x, np.sin(x) * np.cos(x), 'm-', linewidth=2)\n",
        "axes[1, 1].set_title('子图 4', fontsize=12)\n",
        "axes[1, 1].grid(True, alpha=0.3)\n",
        "\n",
        "fig.suptitle('使用总坐标轴标签（共享 x 轴）', fontsize=16, fontweight='bold')\n",
        "fig.supxlabel('统一的 x 轴标签', fontsize=14)  # 总 x 轴标签\n",
        "plt.tight_layout()\n",
        "plt.show()\n",
        "\n",
        "# 使用总坐标轴标签（共享 y 轴）\n",
        "fig, axes = plt.subplots(2, 2, figsize=(12, 8), sharey=True)\n",
        "axes[0, 0].plot(x, np.sin(x), 'b-', linewidth=2)\n",
        "axes[0, 0].set_title('子图 1', fontsize=12)\n",
        "axes[0, 0].grid(True, alpha=0.3)\n",
        "\n",
        "axes[0, 1].plot(x, np.cos(x), 'r-', linewidth=2)\n",
        "axes[0, 1].set_title('子图 2', fontsize=12)\n",
        "axes[0, 1].grid(True, alpha=0.3)\n",
        "\n",
        "axes[1, 0].plot(x, np.tan(x), 'g-', linewidth=2)\n",
        "axes[1, 0].set_title('子图 3', fontsize=12)\n",
        "axes[1, 0].set_ylim(-5, 5)\n",
        "axes[1, 0].grid(True, alpha=0.3)\n",
        "\n",
        "axes[1, 1].plot(x, np.sin(x) * np.cos(x), 'm-', linewidth=2)\n",
        "axes[1, 1].set_title('子图 4', fontsize=12)\n",
        "axes[1, 1].grid(True, alpha=0.3)\n",
        "\n",
        "fig.suptitle('使用总坐标轴标签（共享 y 轴）', fontsize=16, fontweight='bold')\n",
        "fig.supylabel('统一的 y 轴标签', fontsize=14)  # 总 y 轴标签\n",
        "plt.tight_layout()\n",
        "plt.show()\n",
        "\n",
        "# 同时使用总 x 和 y 轴标签\n",
        "fig, axes = plt.subplots(2, 2, figsize=(12, 8), sharex=True, sharey=True)\n",
        "axes[0, 0].plot(x, np.sin(x), 'b-', linewidth=2)\n",
        "axes[0, 0].set_title('子图 1', fontsize=12)\n",
        "axes[0, 0].grid(True, alpha=0.3)\n",
        "\n",
        "axes[0, 1].plot(x, np.cos(x), 'r-', linewidth=2)\n",
        "axes[0, 1].set_title('子图 2', fontsize=12)\n",
        "axes[0, 1].grid(True, alpha=0.3)\n",
        "\n",
        "axes[1, 0].plot(x, np.tan(x), 'g-', linewidth=2)\n",
        "axes[1, 0].set_title('子图 3', fontsize=12)\n",
        "axes[1, 0].set_ylim(-5, 5)\n",
        "axes[1, 0].grid(True, alpha=0.3)\n",
        "\n",
        "axes[1, 1].plot(x, np.sin(x) * np.cos(x), 'm-', linewidth=2)\n",
        "axes[1, 1].set_title('子图 4', fontsize=12)\n",
        "axes[1, 1].grid(True, alpha=0.3)\n",
        "\n",
        "fig.suptitle('同时使用总 x 和 y 轴标签', fontsize=16, fontweight='bold')\n",
        "fig.supxlabel('统一的 x 轴标签', fontsize=14)\n",
        "fig.supylabel('统一的 y 轴标签', fontsize=14)\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": []
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 综合案例：完整的子图布局和标题设置\n",
        "x = np.linspace(0, 10, 100)\n",
        "\n",
        "# 创建一个完整的图表，包含总标题、子图标题和总坐标轴标签\n",
        "fig, axes = plt.subplots(2, 2, figsize=(14, 10), sharex=True, sharey=False)\n",
        "\n",
        "# 第一个子图\n",
        "axes[0, 0].plot(x, np.sin(x), 'b-', linewidth=2, label='sin(x)')\n",
        "axes[0, 0].set_title('正弦函数', fontsize=14, fontweight='bold')\n",
        "axes[0, 0].legend()\n",
        "axes[0, 0].grid(True, alpha=0.3)\n",
        "\n",
        "# 第二个子图\n",
        "axes[0, 1].plot(x, np.cos(x), 'r-', linewidth=2, label='cos(x)')\n",
        "axes[0, 1].set_title('余弦函数', fontsize=14, fontweight='bold')\n",
        "axes[0, 1].legend()\n",
        "axes[0, 1].grid(True, alpha=0.3)\n",
        "\n",
        "# 第三个子图\n",
        "axes[1, 0].plot(x, np.tan(x), 'g-', linewidth=2, label='tan(x)')\n",
        "axes[1, 0].set_title('正切函数', fontsize=14, fontweight='bold')\n",
        "axes[1, 0].set_ylim(-5, 5)\n",
        "axes[1, 0].legend()\n",
        "axes[1, 0].grid(True, alpha=0.3)\n",
        "\n",
        "# 第四个子图\n",
        "axes[1, 1].plot(x, np.sin(x) * np.cos(x), 'm-', linewidth=2, label='sin(x) * cos(x)')\n",
        "axes[1, 1].set_title('正弦与余弦的乘积', fontsize=14, fontweight='bold')\n",
        "axes[1, 1].legend()\n",
        "axes[1, 1].grid(True, alpha=0.3)\n",
        "\n",
        "# 设置总标题\n",
        "fig.suptitle('三角函数可视化', fontsize=20, fontweight='bold', y=0.995)\n",
        "\n",
        "# 设置总坐标轴标签\n",
        "fig.supxlabel('x 轴（弧度）', fontsize=16)\n",
        "fig.supylabel('y 轴值', fontsize=16)\n",
        "\n",
        "# 调整布局，为总标题和标签预留空间\n",
        "plt.subplots_adjust(left=0.1, bottom=0.1, right=0.95, top=0.92, wspace=0.3, hspace=0.4)\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 总结\n",
        "\n",
        "本教程详细讲解了 Matplotlib 子图布局和间距的调整方法，以及标题和标签的设置：\n",
        "\n",
        "### ✅ 调整子图间距\n",
        "- **plt.tight_layout()**：自动调整布局，最简单的方法\n",
        "  - `pad`：控制整体填充\n",
        "  - `h_pad`：垂直方向填充\n",
        "  - `w_pad`：水平方向填充\n",
        "\n",
        "- **plt.subplots_adjust()**：手动精确控制\n",
        "  - `left`, `right`, `top`, `bottom`：边距（0-1 之间）\n",
        "  - `wspace`：水平间距（子图宽度的倍数）\n",
        "  - `hspace`：垂直间距（子图高度的倍数）\n",
        "\n",
        "### ✅ 子图标题和标签\n",
        "- **ax.set_title()**：设置子图标题\n",
        "  - `loc`：标题位置（`'left'`, `'center'`, `'right'`）\n",
        "  - `fontsize`：字体大小\n",
        "  - `fontweight`：字体粗细\n",
        "\n",
        "- **fig.suptitle()**：设置总标题\n",
        "  - 显示在所有子图上方\n",
        "  - 可以调整位置和对齐方式\n",
        "\n",
        "- **fig.supxlabel() 和 fig.supylabel()**：设置总坐标轴标签\n",
        "  - 适用于共享坐标轴的情况\n",
        "  - 避免重复设置标签\n",
        "\n",
        "### 最佳实践\n",
        "1. 优先使用 `tight_layout()` 进行自动调整\n",
        "2. 需要精确控制时使用 `subplots_adjust()`\n",
        "3. 为总标题预留足够的顶部空间\n",
        "4. 共享坐标轴时使用总坐标轴标签\n",
        "5. 保持标题和标签的字体大小协调\n",
        "\n",
        "**下一步**：学习嵌套子图的创建方法。\n"
      ]
    }
  ],
  "metadata": {
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}
